use std::process::Command;
use std::string::ParseError;
use structopt::StructOpt;
use std::collections::HashMap;
use url::Url;

const HD : i32 = 720;
const LOWREZ : i32 = 480;

/// Watch (or try watching) a video over tor, using a combination of mpv and Invidious
/// infrastructure.
#[derive(Debug, StructOpt)]
struct Opt {
    /// Url to watch. Can be Youtube or Invidious
    #[structopt(parse(try_from_str = url_from_str))]
    url: Url,
    /// Pick a higher resolution (default is 480p to not strain the network)
    #[structopt(long = "720")]
    hd: bool,
    /// Audio-only mode (minimal bandwidth)
    #[structopt(long = "audio")]
    audio: bool,

}

fn url_from_str(url: &str) -> Result<Url, ParseError> {
    let parsed: Url = Url::parse(url).unwrap();
    return Ok(parsed);
}

fn mpv_resolution_option (options: &Opt) -> String {
   let rez = match options.hd {
       true => HD.to_string(),
       false => LOWREZ.to_string(),
   };
   return String::from("-ytdl-format=[height<=") + &rez + &String::from("]");
}

fn get_video_id(url: &Url) -> Option<String> {
    for (key, value) in url.query_pairs() {
        if key == "v" {
            return Some(value.to_string());
        }
    }

    let path = url.path();
    if !path.is_empty() {
        if url.path_segments().unwrap().count() == 1 {
            return Some(path.to_string());
        }
    }
    return None;

}


#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let options = Opt::from_args();
    let mpv_rez_option = mpv_resolution_option(&options);
    // let client = reqwest::Client::builder()
    //     .proxy(reqwest::Proxy::all("socks5h://127.0.0.1:9050")?)
    //     .build()?;

    // let resp = client.get("https://torproject.org").send().await?;
    // .json::<HashMap<String, String>>()
    // .await?;
    // println!("{:#?}", resp);

    let mut url = options.url;
    let video_id = get_video_id(&url);
    println!(" id is {}", video_id.unwrap());
    url.set_host(Some("invidious.snopyta.org")).unwrap();
    let url : String = url.into();


    //TODO: fetch the file link from invidious API.
    //https://invidious.snopyta.org/api/v1/videos/ntiGOx4iBxU?fields=videoId,title,hlsUrl,adaptiveFormats,formatStreams
    //audio is under adaptiveFormats
    //video is under formatStreams

    let mut torsocks_args = vec!["-i", "mpv", &url]; 
    if options.audio {
        torsocks_args.push("--vid=no");
    } else {
        torsocks_args.push(&mpv_rez_option);
    }

    let mut child = Command::new("torsocks")
        .args(torsocks_args)
        .spawn()
        .expect("cannot download");

    child.wait().expect("Exited abnormally!");
    Ok(())
}
